﻿#ifndef __UISHADOW_H__
#define __UISHADOW_H__

#pragma once
#include <map>

namespace DuiLib
{

class UILIB_API CShadowUI
{
public:
    friend class CPaintManagerUI;

    CShadowUI(void);
    virtual ~CShadowUI(void);

public:
    // bShow为真时才会创建阴影
    void ShowShadow(bool bShow);    
    bool IsShowShadow() const;

    void DisableShadow(bool bDisable);
    bool IsDisableShadow() const;

    // 算法阴影的函数
    bool SetSize(int NewSize = 0);
    bool SetSharpness(unsigned int NewSharpness = 5);
    bool SetDarkness(unsigned int NewDarkness = 200);
    bool SetPosition(int NewXOffset = 5, int NewYOffset = 5);
    bool SetColor(COLORREF NewColor = 0);

    // 图片阴影的函数
    bool SetImage(LPCTSTR szImage);
    bool SetShadowCorner(RECT rcCorner);    // 九宫格方式描述阴影

    // 把自己的阴影样式复制到传入参数
    bool CopyShadow(CShadowUI* pShadow);

    //    创建阴影窗体，由CPaintManagerUI自动调用,除非自己要单独创建阴影
    void Create(CPaintManagerUI* pPaintManager);
protected:

    //    初始化并注册阴影类
    static bool Initialize(HINSTANCE hInstance);

    // 保存已经附加的窗体句柄和与其关联的阴影类,方便在ParentProc()函数中通过句柄得到阴影类
    static std::map<HWND, CShadowUI *>& GetShadowMap();

    //    子类化父窗体
    static LRESULT CALLBACK ParentProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    // 父窗体改变大小，移动，或者主动重绘阴影时调用
    void Update(HWND hParent);

    // 通过算法计算阴影
    void MakeShadow(UINT32 *pShadBits, HWND hParent, RECT *rcParent);

    // 计算alpha预乘值
    inline DWORD PreMultiply(COLORREF cl, unsigned char nAlpha)
    {
        return (GetRValue(cl) * (DWORD)nAlpha / 255) |
            (GetGValue(cl) * (DWORD)nAlpha / 255) << 8 |
            (GetBValue(cl) * (DWORD)nAlpha / 255) << 16 ;
    }

protected:
    enum ShadowStatus
    {
        SS_ENABLED = 1,                // Shadow is enabled, if not, the following one is always false
        SS_VISABLE = 1 << 1,        // Shadow window is visible
        SS_PARENTVISIBLE = 1<< 2    // Parent window is visible, if not, the above one is always false
    };


    static bool s_bHasInit;

    CPaintManagerUI    *m_pManager;        // 父窗体的CPaintManagerUI，用来获取素材资源和父窗体句柄
    HWND             m_hWnd;            // 阴影窗体的句柄
    LONG_PTR         m_OriParentProc;    // 子类化父窗体
    BYTE             m_Status;
    bool             m_bIsImageMode;    // 是否为图片阴影模式
    bool             m_bIsShowShadow;    // 是否要显示阴影
    bool            m_bIsDisableShadow;
    // 算法阴影成员变量
    unsigned char m_nDarkness;    // Darkness, transparency of blurred area
    unsigned char m_nSharpness;    // Sharpness, width of blurred border of shadow window
    signed char m_nSize;    // Shadow window size, relative to parent window size

    // The X and Y offsets of shadow window,
    // relative to the parent window, at center of both windows (not top-left corner), signed
    signed char m_nxOffset;
    signed char m_nyOffset;

    // Restore last parent window size, used to determine the update strategy when parent window is resized
    LPARAM m_WndSize;

    // Set this to true if the shadow should not be update until next WM_PAINT is received
    bool m_bUpdate;

    COLORREF m_Color;    // Color of shadow

    // 图片阴影成员变量
    CDuiString    m_sShadowImage;
    RECT        m_rcShadowCorner;
};

}

#endif //__UISHADOW_H__